<?php
/*
 * XenonPHP i18n class, By Olivier St-Laurent
 * Version 1.0
 *
 * Usage :
 *      new i18n($database, $_GET['lang']); // Must be called before the Action and After the database initialisation.
 *        // First parameter is the database. It can be the following :
 *        //    An instance of X_mysql to connect to the database to fetch texts
 *        //    Null or False if using ONLY runtime hardcoded texts
 *        // Second parameter is a reference to the lang that has just been set by the user (ie: A link to change language with a GET param)
 *
 *      __('hello')
 *        // will fetch the text with the ID 'hello'. If it does not exist, it will be outputed as is.
 *
 *      __('hello', $name)
 *        // We consider that the texts in the database are like this : id:'hello', en:'Hello %name%', fr:'Bonjour %name%'.
 *        // The %name% will be replaced by the value of $name.
 *        // For multiple replaced texts, you may use an associative array like this : __('hello', array('name'=>$name, ....))
 *
 *      __(array('en'=>"hello %name%", 'fr'=>"Bonjour %name%"), $name)
 *        // Same as above, but here we hardcode the texts, we are not using the database to fetch the texts.
 *
 *      __(array("hello %name%", "Bonjour %name%"), $name)
 *        // Same as above, without the language keys (Not an associative array).
 *        // It will use the keys from i18n::$langs_active, in the same order.
 *
 *
 *      // PHP Code to include if not using XenonPHP :
  function __($text, $replace=null) {
  if (!empty(i18n::$defaultInstance)) {
  return i18n::$defaultInstance->__($text, $replace);
  } else {
  if (is_array($text)) {
  foreach ($text as $text) {
  if (!empty($text)) break;
  }
  }
  if ($replace !== null) {
  if (is_array($replace)) {
  foreach ($replace as $key => $str) {
  $text = preg_replace("#%".preg_quote($key,"#")."%#", $str, $text);
  }
  } else {
  $text = preg_replace("#%.+%#U", $replace, $text);
  }
  }
  return $text;
  }
  }
 *
 */

class i18n
{
    static $cache_enabled = false; // Enables Session caching, texts will be fetched from database once and saved in the SESSION.
    static $cache_autofill = false; // Fill cache automatically with all texts on first script execution
    static $langs_active = array('en' => true, 'fr' => true, 'es' => false); // True for active langs, false for inactive. Do not change the order of langs after using non-associative arrays for hardcoded texts.
    static $db_table = 'i18n';
    static $defaultInstance = null;
    public $engine = null;
    public $langs = array();
    public $texts = null;
    public $db = null;

    public static function changeLangLink($newLang)
    {
        $url = $_SERVER['REQUEST_URI'];
        foreach (self::$langs_active as $lang => $active) {
            $url = str_replace('/' . $lang . '/', '/', $url);
        }
        return '/' . $newLang . $url;
    }

    public function __construct(&$getLang = null, $db = null, $overwriteDefaultInstance = false)
    {
        if (!empty($getLang)) {
            $_SESSION['X_lang'] = $getLang;
        }
        if (!defined('LANG') && !empty($_SESSION['X_lang'])) {
            define('LANG', $_SESSION['X_lang']);
        }
        if ($overwriteDefaultInstance || empty(self::$defaultInstance)) {
            self::$defaultInstance = $this;
        }
        $this->db = $db;
        if (self::$cache_enabled && isset($_SESSION['X_i18n_cache'])) {
            $this->texts = $_SESSION['X_i18n_cache'];
        }
        $str_browser_langs = array();
        $browser_langs = array();
        if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
            $str_browser_langs = preg_split("#;#", $_SERVER['HTTP_ACCEPT_LANGUAGE']);
            $str_browser_langs[0] = strtolower($str_browser_langs[0]);
            $browser_langs = preg_split("#,#", $str_browser_langs[0]);
        }
        $this->langs[] = & $getLang;
        $this->langs[] = & $_SESSION['X_lang'];
        foreach ($browser_langs as $bl) {
            if (!in_array($bl, $this->langs) && !empty(self::$langs_active[$bl])) {
                $this->langs[] = $bl;
                if (!defined('LANG')) {
                    define('LANG', $bl);
                }
            }
        }
        foreach (self::$langs_active as $l => $active) {
            if ($active && !in_array($l, $this->langs)) {
                $this->langs[] = $l;
                if (!defined('LANG')) {
                    define('LANG', $l);
                }
            }
        }
        if (self::$cache_autofill) {
            $this->getTexts();
        }
    }

    public function __($text, $replace = null)
    {
        if (!is_array($text)) {
            if (is_array($this->texts) && array_key_exists($text, $this->texts)) {
                $text = $this->texts[$text];
            } else if ($this->texts !== false) {
                $this->getTexts();
                if (is_array($this->texts) && array_key_exists($text, $this->texts)) {
                    $text = $this->texts[$text];
                }
            }
        }
        if (is_array($text)) {

            foreach ($this->langs as $lang) {
                if (!empty($lang)) {
                    foreach (array(
                    strtolower($lang),
                    strtoupper($lang),
                    array_search(strtolower($lang), array_keys(self::$langs_active)),
                    array_search(strtoupper($lang), array_keys(self::$langs_active)),
                    ) as $search) {
                        if (!empty($text[$search])) {
                            $text = $text[$search];
                            break 2;
                        }
                    }
                }
            }
        }
        if (is_array($text)) {
            foreach ($text as $text) {
                if (!empty($text))
                    break;
            }
        }
        if (!empty($text) && $replace !== null) {
            if (is_array($replace)) {
                foreach ($replace as $key => $str) {
                    $text = preg_replace("#%" . preg_quote($key, "#") . "%#i", $str, $text);
                }
            } else {
                $text = preg_replace("#%.+%#U", $replace, $text);
            }
        }
        return $text;
    }

    public function getTexts()
    {
        if ($this->db instanceof X_mysql) {
            $this->engine = "mysql";
            if (empty($this->texts)) {
                $this->texts = $this->fetchAllFromMysql();
                if (self::$cache_enabled && !empty($this->texts)) {
                    $_SESSION['X_i18n_cache'] = $this->texts;
                }
            }
        } else if (is_string($this->db)) {
            $this->engine = "text";
            // TODO : Fetch All From Text File
        }
    }

    static function getLangs()
    {
        $langs = array();
        foreach (self::$defaultInstance->langs as $lang) {
            $lang = trim(strtolower($lang));
            if (!empty($lang) && !in_array($lang, $langs)) {
                $langs[] = $lang;
            }
        }
        return implode(', ', $langs);
    }

    public function fetchAllFromMysql()
    {
        $mysql = new X_mysql_query(self::$db_table, $this->db->link);
        return $mysql->fetchAll(true);
    }

    static function getLang()
    {
        foreach (self::$defaultInstance->langs as $lang) {
            $lang = trim(strtolower($lang));
            if (!empty($lang) && !empty(self::$langs_active[$lang])) {
                return $lang;
            }
        }
    }

}
